home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 422_02 / dosutil / validate.c < prev   
C/C++ Source or Header  |  1994-03-20  |  9KB  |  259 lines

  1. /**********************************************************************\
  2. VALIDATE -     Portable "C" version of a CRC validation program which uses
  3.             the same mechanisms as McAfee's VALIDATE program.
  4.  
  5. Arguments:    Filename(s) - The name(s) of the file(s) to be checked.
  6.             (See complete documentation following code in this file)
  7.  
  8. Author: Gary P. Mussar (gmussar on BIX)
  9.  
  10. This code is released to the public domain. There are no restrictions,
  11. however, acknowledging the author by keeping this comment around would
  12. be appreciated.                      Compile command: cc validate -fop
  13. \**********************************************************************/
  14.  
  15. #include <stdio.h>
  16. #include <file.h>
  17.  
  18. char version[] = {"Portable VALIDATE (Public Domain) V1.0 1991-01-05"};
  19.  
  20. /**********************************************************************\
  21. The following is used to define the types of variable used to hold or
  22. manipulate CRCs. The 16 bit CRCs require a data type which is at least
  23. 16 bits. In addition, the data bits reserved for the CRC must be
  24. manipulated in an unsigned fashion.  It is possible to define a data
  25. type which is larger than required to hold the CRC, however, this is an
  26. inefficient use of memory and usually results in less efficient code.
  27. \**********************************************************************/
  28. #define CRC16 unsigned
  29.  
  30. /**********************************************************************\
  31. The coefficient of each term of the generator polynomial is represented
  32. by a bit in the polynomial array (except for the highest order term
  33. which is always assumed to be 1).  The coefficient for the second
  34. highest term in the LSB of the first byte of the polynomial array.
  35.  
  36. CRC Check 1
  37.   Polynomial   x^16 + x^15 + x^2 + 1    (16 bit BCS polynomial)
  38.   Generator is pre-initialized to 0x0000
  39.  
  40. CRC Check 2
  41.   Polynomial   x^16 + x^15 + x^10 + x^3
  42.   Generator is pre-initialized to 0x0000
  43. \**********************************************************************/
  44. CRC16 crcchk1[256];                    /* Fast lookup table */
  45. CRC16 poly_crcchk1 = {0xA001};        /* Generator polynomial */
  46. CRC16 init_crcchk1 = {0x0000};        /* Pre-init value */
  47. CRC16 crc_crcchk1;                    /* CRC accumulator */
  48.  
  49. CRC16 crcchk2[256];                    /* Fast lookup table */
  50. CRC16 poly_crcchk2 = {0x1021};        /* Generator polynomial */
  51. CRC16 init_crcchk2 = {0x0000};        /* Pre-init value */
  52. CRC16 crc_crcchk2;                    /* CRC accumulator */
  53.  
  54. /* File stuff. The file is read (and CRCs calculated) in chunks. The
  55.    size of a chunk is determined by the size of buff[] */
  56. FILE *fp;
  57. char buff[8192];
  58.  
  59. /**********************************************************************\
  60. Utilities for fast CRC using table lookup
  61.  
  62. CRC calculations are performed one byte at a time using a table lookup
  63. mechanism.  Two routines are provided: one to initialize the CRC lookup
  64. table; and one to perform the CRC calculation over an array of bytes.
  65.  
  66. A CRC is the remainder produced by dividing a generator polynomial into
  67. a data polynomial using binary arthimetic (XORs).  The data polynomial
  68. is formed by using each bit of the data as a coefficient of a term in
  69. the polynomial.  These utilities assume the data communications ordering
  70. of bits for the data polynomial, ie. the LSB of the first byte of data
  71. is the coefficient of the highest term of the polynomial, etc..
  72.  
  73. I_CRC16  -  Initialize the 256 entry CRC lookup table based on the
  74.             specified generator polynomial.
  75. Input:
  76.    Table[256]    - Lookup table
  77.    GenPolynomial - Generator polynomial
  78.  
  79. F_CRC16  -  Calculate CRC over an array of characters using fast
  80.             table lookup.
  81. Input:
  82.    Table[256]    - Lookup table
  83.    *CRC          - Pointer to the variable containing the result of
  84.                    CRC calculations of previous characters. The CRC
  85.                    variable must be initialized to a known value
  86.                    before the first call to this routine.
  87.    *dataptr      - Pointer to array of characters to be included in
  88.                    the CRC calculation.
  89.    count         - Number of characters in the array.
  90. \**********************************************************************/
  91. I_CRC16(Table, GenPolynomial)
  92.     CRC16 Table[256];
  93.     CRC16 GenPolynomial;
  94. {
  95.     int i;
  96.     CRC16 crc;
  97.  
  98.     for (i = 0; i < 256; ++i)
  99.     {
  100.         crc = (CRC16) i;
  101.         crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
  102.         crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
  103.         crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
  104.         crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
  105.         crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
  106.         crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
  107.         crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
  108.         crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
  109.  
  110.         Table[i] = crc;
  111.     }
  112. }
  113.  
  114. F_CRC16(Table, CRC, dataptr, count)
  115.     CRC16 Table[256];
  116.     CRC16 *CRC;
  117.     unsigned char *dataptr;
  118.     unsigned int count;
  119. {
  120.     CRC16 temp_crc;
  121.  
  122.     for (temp_crc = *CRC; count; --count)
  123.     {
  124.         temp_crc = (temp_crc >> 8) ^ Table[(temp_crc & 0xff) ^ *dataptr++];
  125.     }
  126.  
  127.     *CRC = temp_crc;
  128. }
  129.  
  130. /**********************************************************************\
  131. Mainline
  132.  
  133. Each file specified on the input line is opened (in binary mode) and two
  134. CRCs are calculated over the data.
  135.  
  136. The CRC generators are initialized to 0 which means that null bytes (00)
  137. added to the front of a file will not affect the CRC (sigh, when will
  138. people ever learn).  Hopefully the file length will catch these kinds of
  139. problems.
  140. \**********************************************************************/
  141. main(argc, argv)
  142.     int argc;
  143.     char *argv[];
  144. {
  145.     unsigned len, files, bcount_h, bcount_l;
  146.  
  147.     fprintf(stderr, "%s\n", version);
  148.  
  149.     /* We expect 1 or more arguments */
  150.     if (argc < 2)
  151.     {
  152.         fprintf(stderr, "This program prints the validation information for a file.\n");
  153.         fprintf(stderr, "Examples:\n");
  154.         fprintf(stderr, "          VALIDATE SCAN.EXE\n");
  155.         fprintf(stderr, "          VALIDATE SCANRES.EXE\n");
  156.         exit(1);
  157.     }
  158.  
  159.     /* Set up CRC tables */
  160.     I_CRC16(crcchk1, poly_crcchk1);
  161.     I_CRC16(crcchk2, poly_crcchk2);
  162.  
  163.     /* Loop through each filename on the invocation line */
  164.     for (files = 1; files < argc; ++files)
  165.     {
  166.         printf("\n          File Name:  %s\n", argv[files]);
  167.         fp=open(argv[files],F_READ);
  168.         if (!fp)
  169.         {
  170.             fprintf(stderr, "\n Sorry, I cannot open the input file.\n");
  171.             continue;
  172.         }
  173.  
  174.         /* Byte count and CRC generators to initial values */
  175.         bcount_h = bcount_l = 0;
  176.         crc_crcchk1 = init_crcchk1;
  177.         crc_crcchk2 = init_crcchk2;
  178.  
  179.         /* Read the file in chunks until done */
  180.         while ((len = read(buff, sizeof(buff), fp)) != 0)
  181.         {
  182.             /* Calculate CRC over this part of file */
  183.             F_CRC16(crcchk1, &crc_crcchk1, buff, len);
  184.             F_CRC16(crcchk2, &crc_crcchk2, buff, len);
  185.  
  186.             /* Byte count of file */
  187.             if((bcount_l += len) > 10000)
  188.                 ++bcount_h, bcount_l -= 10000;
  189.         }
  190.  
  191.         /* Give the user the results */
  192.         printf("               Size:  %u%04u\n", bcount_h, bcount_l);
  193.         printf("File Authentication:\n");
  194.         printf("     Check Method 1 - %04x\n", crc_crcchk1);
  195.         printf("     Check Method 2 - %04x\n", crc_crcchk2);
  196.         close(fp);
  197.     }
  198. }
  199.  
  200.  
  201.  
  202. /*
  203. Portable VALIDATE is a file authentication program which can be used to
  204. check software for signs of tampering.  The program calculates two check
  205. codes over the data in a file by using two different CRC algorithms.
  206. The results can be checked against values provided by the author of the
  207. tested file or a list of values provided by a reliable source.  One such
  208. reliable source is the Computer Virus Industry Association which
  209. maintains validation data for various shareware programs on-line.  The
  210. CVIA bulletin board can be reached at (408) 988-4004.  The user needs to
  211. perform the following steps when validating a program:
  212.  
  213.   - obtain the authentication numbers from a reliable source.
  214.   - run Portable VALIDATE against the desired file.
  215.   - compare the check codes produced by Portable VALIDATE against the
  216.     reliable authentication numbers.
  217.  
  218. If the numbers match, the user can be reasonably assured that the file
  219. or program has not been corrupte